package com.accesshollywood.GL;

import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glInitNames;
import static org.lwjgl.opengl.GL11.glTexCoord2f;
import static org.lwjgl.opengl.GL11.glVertex2f;

import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

public class MasterControl extends AnimObject {
	public enum RENDER_MODE {
		RENDER, SELECTION
	};

	public ArrayList<AnimObject>	objects;
	public static final boolean		POLITE_KEY			= true;
	public static final float		COUPLE_PEOPLE_RATIO	= 1.0f / 10.0f;
	public static final int			BUTTON_HEIGHT		= 100;

	public Zone						coupleZone;
	public Zone						peopleZone;
	public Zone						buttonZone;
	public Zone						finalZone;
	public Zone						highlightZone;

	public Match					match;
	public NoMatch					noMatch;
	public Done						done;

	public int						numSelections		= 0;
	public int						numCouples			= 0;

	public boolean					fromLeft			= true;
	public boolean					isReady;

	private Texture					texture;

	public File						photoPath;
	public File						couplePath;
	public File						bgPath;

	public MasterControl() {
		super();

		try {
			photoPath = new File(new File(".").getCanonicalFile() + "\\photos\\singles");
			couplePath = new File(new File(".").getCanonicalFile() + "\\photos\\couples");
			bgPath = new File(new File(".").getCanonicalFile() + "\\photos");
		} catch (IOException e) {
			e.printStackTrace();
		}

		// glSelectBuffer(size, buffer);

		objects = new ArrayList<AnimObject>();

		isReady = false;
		createZones();
		setupZones();

		makeTestObjects();
	}

	public void createZones() {
		/*
		 * coupleZone = new Zone(MatchUpGLMain.SCREEN_WIDTH * 0.05f,
		 * -MatchUpGLMain.SCREEN_HEIGHT * COUPLE_PEOPLE_RATIO,
		 * MatchUpGLMain.SCREEN_WIDTH * 0.95f, MatchUpGLMain.SCREEN_HEIGHT *
		 * COUPLE_PEOPLE_RATIO - BUTTON_HEIGHT / 2.0f,
		 * Zone.TYPE.COUPLE);
		 * coupleZone.marginRatio = 0.1f;
		 * coupleZone.masterControl = this;
		 */
		buttonZone = new Zone(MatchUpGLMain.SCREEN_WIDTH * 0.05f, MatchUpGLMain.SCREEN_HEIGHT * .05f, MatchUpGLMain.SCREEN_WIDTH * 0.95f, MatchUpGLMain.SCREEN_HEIGHT * COUPLE_PEOPLE_RATIO,
				Zone.TYPE.COUPLE);
		buttonZone.marginRatio = 0.1f;
		buttonZone.masterControl = this;

		try {
			match = new Match(TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(bgPath.getCanonicalPath() + "\\match.png")));
			noMatch = new NoMatch(TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(bgPath.getCanonicalPath() + "\\noMatch.png")));
			done = new Done(TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(bgPath.getCanonicalPath() + "\\xDone.png")));
		} catch (IOException e) {
			e.printStackTrace();
		}

		buttonZone.addMember(match);
		buttonZone.addMember(noMatch);
		buttonZone.addMember(done);

		peopleZone = new Zone(MatchUpGLMain.SCREEN_WIDTH * 0.025f, MatchUpGLMain.SCREEN_HEIGHT * 1.05f, MatchUpGLMain.SCREEN_WIDTH * 0.95f, MatchUpGLMain.SCREEN_HEIGHT * 0.55f * (1.0f - COUPLE_PEOPLE_RATIO), Zone.TYPE.PEOPLE);
		peopleZone.marginRatio = 0.225f;
		peopleZone.masterControl = this;

		finalZone = new Zone(MatchUpGLMain.SCREEN_WIDTH * 0.085f, MatchUpGLMain.SCREEN_HEIGHT * 1.05f, MatchUpGLMain.SCREEN_WIDTH * 0.85f, MatchUpGLMain.SCREEN_HEIGHT * 1.0f, Zone.TYPE.FINAL);
		finalZone.marginRatio = 0.225f;
		finalZone.masterControl = this;
	}

	public void setupZones() {
		try {
			texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(bgPath.getCanonicalPath() + "\\MM_BG.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		peopleZone.loadFaceArray(photoPath);

		finalZone.loadFaceArray(couplePath);
	}

	public void displayZones() {
		System.out.println("displayZones");
		children.add(peopleZone);
		children.add(buttonZone);
		children.add(finalZone);

		Keyframe newKey = new Keyframe();
		newKey.setPosXYZ(peopleZone.posCurr);
		newKey.setPosY(MatchUpGLMain.SCREEN_HEIGHT * .15f);
		newKey.setFrames(30);
		peopleZone.addKeyframe(newKey);

		peopleZone.processNextKeyframe(!POLITE_KEY);
	}

	public void moveToCouples(Picture currPicture) {
		// coupleZone.addMember(new Couple());
		// coupleZone.reLayout(Zone.ANIMATE_RELAYOUT);
		Couple currCouple = null;
		for (int i = 0; i < coupleZone.children.size(); i++) {
			currCouple = (Couple) coupleZone.children.get(i);
			if (coupleZone.children.size() == 1) { // there's already the guide
				// as a child, but no actual
				// images
				break;
			} else if (coupleZone.children.size() == 2) {
				break;
			} else {
				// keep looking
			}
		}
		if (currCouple != null) {
			currPicture.setPrelimCoupleMode();
			currPicture.unselectMe();
			Keyframe newKey = new Keyframe();
			newKey.setPosXYZ(new Vector3f((currCouple.children.size() - 2) * 730.0f + 365.0f, 0.0f, 0.0f));
			newKey.setScaleXYZ(new Vector3f(1.0f, 1.0f, 1.0f));
			newKey.setAlpha(1.0f);
			newKey.setFrames(20);
			currPicture.addKeyframe(newKey);
			currPicture.swapParents(peopleZone, currCouple);
			currPicture.processNextKeyframe(!POLITE_KEY);
			if (peopleZone.children.size() > 0) {
				refreshZoneSelections(peopleZone);
				peopleZone.reLayout(Zone.ANIMATE_RELAYOUT);
			}
		}
	}

	public void moveOutOfCouples(Couple currCouple) {
		for (int i = 1; i < 3; i++) {
			Picture currPicture = (Picture) currCouple.children.get(1);
			currPicture.unsetPrelimCoupleMode();
			Keyframe newKey = new Keyframe();
			newKey.setPosXYZ(new Vector3f((currCouple.children.size() - 2) * 730 + 365, 0, 0));
			newKey.setAlpha(1.0f);
			newKey.setFrames(20);
			currPicture.addKeyframe(newKey);
			currPicture.swapParents(currCouple, peopleZone);
			currPicture.processNextKeyframe(!POLITE_KEY);
			if (peopleZone.children.size() > 0) {
				refreshZoneSelections(peopleZone);
				peopleZone.reLayout(Zone.ANIMATE_RELAYOUT);
			}
		}
		coupleZone.children.remove(currCouple);
		coupleZone.reLayout(Zone.ANIMATE_RELAYOUT);
	}

	public void setAsReady() {
		isReady = true;
		System.out.println("ready!");
		displayZones();
	}

	public void addMemberToZone(AnimObject newMember, Zone whichZone) {
		whichZone.addMember(newMember);
	}

	public void switchToCouples() {
		Keyframe newKey = new Keyframe();
		newKey.setPosY(-1000);
		buttonZone.addKeyframe(newKey);
		buttonZone.processNextKeyframe(POLITE_KEY);

		Keyframe newKey2 = new Keyframe();
		newKey2.setPosXYZ(finalZone.posCurr);
		newKey2.setPosY(0);
		finalZone.addKeyframe(newKey2);
		finalZone.processNextKeyframe(POLITE_KEY);
	}

	public void refreshZoneSelections(Zone whichZone) {
		int origNumSelections = numSelections;
		numSelections = 0;
		for (int i = 0; i < whichZone.children.size(); i++) {
			Picture currPicture = (Picture) whichZone.children.get(i);
			if (currPicture.isSelected()) {
				numSelections++;
			}
		}
		if (numSelections == 2) {
		} else {
			if (origNumSelections == 2) {
			}
		}

		for (int i = 0; i < whichZone.children.size(); i++) {
			Picture currPicture = (Picture) whichZone.children.get(i);
			if (numSelections > 0) {
				if (!currPicture.isSelected()) {
					currPicture.shrink();
				}
			} else {
				currPicture.goHome();
			}
		}
	}

	public void renderGL() {
		glInitNames();
		if (texture != null) {
			texture.bind();
			glBegin(GL_QUADS);
			glTexCoord2f(0, 0);
			glVertex2f(0, 0);

			glTexCoord2f(1920.0f / 2048.0f, 0);
			glVertex2f(MatchUpGLMain.SCREEN_WIDTH, 0);

			glTexCoord2f(1920.0f / 2048.0f, 1080.0f / 2048.0f);
			glVertex2f(MatchUpGLMain.SCREEN_WIDTH, MatchUpGLMain.SCREEN_HEIGHT);

			glTexCoord2f(0, 1080.0f / 2048.0f);
			glVertex2f(0, MatchUpGLMain.SCREEN_HEIGHT);
			glEnd();
		}
	}

	public AnimObject getClickedObj(int mouseX, int mouseY) {
		Vector3f clickPos;
		IntBuffer viewport = BufferUtils.createIntBuffer(16);
		FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
		FloatBuffer projection = BufferUtils.createFloatBuffer(16);
		FloatBuffer winZ = BufferUtils.createFloatBuffer(1);
		float winX, winY;
		FloatBuffer position = BufferUtils.createFloatBuffer(3);

		GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
		GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
		GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);

		winX = (float) mouseX;
		winY = (float) viewport.get(3) - (float) mouseY;

		GL11.glReadPixels(mouseX, (int) winY, 1, 1, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, winZ);

		GLU.gluUnProject(winX, winY, winZ.get(), modelview, projection, viewport, position);

		clickPos = new Vector3f(position.get(), position.get(), position.get());

		position.clear();

		Picture currPicture = null;
		for (int i = 0; i < children.size(); i++) {
			Zone currZone = (Zone) children.get(i);
			for (int j = 0; j < currZone.children.size(); j++) {
				currPicture = (Picture) currZone.children.get(j);
				GLU.gluUnProject(currPicture.getLeft(), currPicture.getTop(), 0, modelview, projection, viewport, position);
				float left = position.get();
				float top = position.get();
				position.clear();
				GLU.gluUnProject(currPicture.getRight(), currPicture.getBottom(), 0, modelview, projection, viewport, position);
				float right = position.get();
				float bottom = position.get();
				position.clear();

				// System.out.println(left+"  "+top+"  "+right+"  "+bottom);

				if (left < clickPos.x && right > clickPos.x && top < clickPos.y && bottom > clickPos.y) {
					System.out.println("A hit!  A palpable hit!");
					return currPicture;
				}
			}
		}
		return null;
	}

	public Vector3f getMousePosition(int mouseX, int mouseY) {
		IntBuffer viewport = BufferUtils.createIntBuffer(16);
		FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
		FloatBuffer projection = BufferUtils.createFloatBuffer(16);
		FloatBuffer winZ = BufferUtils.createFloatBuffer(1);
		float winX, winY;
		FloatBuffer position = BufferUtils.createFloatBuffer(3);

		GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
		GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
		GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);

		winX = (float) mouseX;
		winY = (float) viewport.get(3) - (float) mouseY;

		GL11.glReadPixels(mouseX, (int) winY, 1, 1, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, winZ);

		GLU.gluUnProject(winX, winY, winZ.get(), modelview, projection, viewport, position);

		return new Vector3f(position.get(), position.get(), position.get());
	}

	public void refreshHighlightSelection(Picture currSelected) {
		for (int i = 0; i < highlightZone.children.size(); i++) {
			Picture currPicture = (Picture) highlightZone.children.get(i);
			if (currPicture != currSelected) {
				currPicture.deselectMe();
			}
			// if(numSelections > 0){
			// if(!currPicture.isSelected()){
			// currPicture.shrinkTiny();
			// }
			// }else{
			// currPicture.resetSize();
			// }
		}
	}

	public void makeTestObjects() {
		// glColor3f(1.0f, 0.0f, 1.0f);
		Picture newPicture = new Picture(null);

		// children.add(newPicture);
		Keyframe newKeyframe = new Keyframe();
		newKeyframe.setPosX(100);
		newKeyframe.setRotZ((float) (90));
		newKeyframe.setFrames(30);
		newPicture.addKeyframe(newKeyframe);

		newKeyframe = new Keyframe();
		newKeyframe.setPosX(1000);
		newKeyframe.setPosY(1000);
		newKeyframe.setPosZ(1000);
		newKeyframe.setRotZ((float) (-360));
		newKeyframe.setScaleXYZ(new Vector3f(50f, 0.1f, 1.0f));
		newKeyframe.setFrames(100);
		newPicture.addKeyframe(newKeyframe);

		newPicture.processNextKeyframe(true);
	}
}
